#ifndef DOTPROCESSOR_H
#define DOTPROCESSOR_H

#include <string>
#include <vector>
#include <iostream>
#include <fstream>

#ifdef linux
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <sys/wait.h>
#else
  #include <windows.h>
  #include <stdio.h>
  #include <tchar.h>

typedef std::basic_string<TCHAR> tstring;  
 
TCHAR* StringToTCHAR(const std::string& s)
{
	TCHAR *param=new TCHAR[s.size()+1];
	param[s.size()]=0;
	//As much as we'd love to, we can't use memcpy() because
	//sizeof(TCHAR)==sizeof(char) may not be true:
	std::copy(s.begin(),s.end(),param);
	return param;
}

#endif

class DotProcessor {
public:

  DotProcessor() {
    viewer = "dotty";
    format = "dot";
  }

  std::string viewer;
  std::string format;

  void show(std::string dot_output) {
    using namespace std;
    cout << "Running dot (close window to continue)... ";
    cout.flush();
    string file = "out."+format;
    ofstream out("out.dot");
    out << dot_output << endl;
    out.flush();
    out.close();
    string program = "dotty";
    vector<string> args;
    args.push_back("out." + format);
    runProcess(program, args);

    cout << "done." << endl;
  }

  void runProcess(const std::string &program, const std::vector<std::string> &args) {
    std::cout << "in" << std::endl;
#ifdef linux
    char *c_args[args.size()+2];
    c_args[0] = new char[4];
    c_args[0] = (char*)"dotty\0";
    for (size_t i = 0; i < args.size(); i++) {
      c_args[i+1] = new char[args[i].size()+1];
      memcpy(c_args[i+1], &args[i][0], args[i].size());
      c_args[i+1][args[i].size()] = 0;
    }
    c_args[args.size()+1] = 0;

    int status;
    int child = fork();

    if (child)
      while(wait(&status) != child);
    else
      execvp(program.c_str(), c_args);
    std::cout << "done" << std::endl;
#else
    std::string run = program;
    for (size_t i = 0; i < args.size(); i++) {
      run += " " + args[i];
    }
    
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( !CreateProcess( NULL,   // No module name (use command line)
        StringToTCHAR(run),        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
		) {
		std::cout << "error" << std::endl;
	}
	std::cout << StringToTCHAR(program) << std::endl;
    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread ); 
#endif
  }
};

#endif // DOTPROCESSOR_H
